package cn.nexd.location.indoor.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

/**
 * Created by codngfish on 16/5/17.
 */
public final class ThreadPoolManager {

    private ExecutorService executorService = null;
    private ScheduledExecutorService scheduledExecutorService = null;

    public static ThreadPoolManager getThreadPoolManagerInstance() {
        return ThreadPoolManagerClassHandler.THREAD_POOL_MANAGER;
    }


    private ThreadPoolManager() {
        executorService = ThreadPoolFactory.newCachedThreadPool();
        scheduledExecutorService = ThreadPoolFactory.newScheduledThreadPool(5);
        //        handlerWifiCollectorLifecycleThreadPool = ThreadPoolFactory.newScheduledThreadPool(2);
    }


    public void start() {
        if (scheduledExecutorService == null) {
            scheduledExecutorService = ThreadPoolFactory.newScheduledThreadPool(5);
        }

        if (executorService == null) {
            executorService = ThreadPoolFactory.newCachedThreadPool();
        }
    }

    public void addTaskExecutorService(Runnable runnable) {
        executorService.execute(runnable);
    }

    public void addTaskScheduledExecutorService(Runnable runnable, long delay, long period) {
        scheduledExecutorService.scheduleAtFixedRate(runnable, delay, period, TimeUnit.MILLISECONDS);
    }

    public void shutdownThreadPool() {
        if (scheduledExecutorService != null) {
            scheduledExecutorService.shutdown();
            scheduledExecutorService = null;
        }

        if (executorService != null) {
            executorService.shutdown();
            executorService = null;
        }
    }

    public static class ThreadPoolFactory {
        /**
         * 该方法返回一个固定线程数量的线程池，该线程池中的线程数量始终不变，即不会再创建新的线程，也不会销毁已经创建好的线程，
         * 自始自终都是那几个固定的线程在工作，所以该线程池可以控制线程的最大并发数。
         *
         * @return
         */
        public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
            return Executors.newFixedThreadPool(nThreads, threadFactory);
        }

        /**
         * 该方法返回一个固定线程数量的线程池，该线程池中的线程数量始终不变，即不会再创建新的线程，也不会销毁已经创建好的线程，
         * 自始自终都是那几个固定的线程在工作，所以该线程池可以控制线程的最大并发数。
         *
         * @return
         */
        public static ExecutorService newFixedThreadPool(int nThreads) {
            return Executors.newFixedThreadPool(nThreads);
        }

        /**
         * 该方法返回一个可以根据实际情况调整线程池中线程的数量的线程池。即该线程池中的线程数量不确定，是根据实际情况动态调整的。
         *
         * @return
         */
        public static ExecutorService newCachedThreadPool() {
            return Executors.newCachedThreadPool();
        }

        /**
         * 该方法返回一个可以根据实际情况调整线程池中线程的数量的线程池。即该线程池中的线程数量不确定，是根据实际情况动态调整的。
         *
         * @return
         */
        public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
            return Executors.newCachedThreadPool(threadFactory);
        }

        /**
         * 该方法返回一个只有一个线程的线程池，即每次只能执行一个线程任务，多余的任务会保存到一个任务队列中，
         * 等待这一个线程空闲，当这个线程空闲了再按FIFO方式顺序执行任务队列中的任务。
         *
         * @return
         */
        public static ExecutorService newSingleThreadExecutor() {
            return Executors.newSingleThreadExecutor();

        }

        /**
         * 该方法返回一个只有一个线程的线程池，即每次只能执行一个线程任务，多余的任务会保存到一个任务队列中，
         * 等待这一个线程空闲，当这个线程空闲了再按FIFO方式顺序执行任务队列中的任务。
         *
         * @return
         */
        public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
            return Executors.newSingleThreadExecutor(threadFactory);

        }

        /**
         * 该方法返回一个可以控制线程池内线程定时或周期性执行某任务的线程池。
         *
         * @return
         */
        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
            return Executors.newScheduledThreadPool(corePoolSize);
        }

        /**
         * 该方法返回一个可以控制线程池内线程定时或周期性执行某任务的线程池。
         *
         * @return
         */
        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {
            return Executors.newScheduledThreadPool(corePoolSize, threadFactory);
        }

        /**
         * 该方法返回一个可以控制线程池内线程定时或周期性执行某任务的线程池。只不过和上面的区别是该线程池大小为1，而上面的可以指定线程池的大小。
         *
         * @return
         */
        public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
            return Executors.newSingleThreadScheduledExecutor();
        }

        /**
         * 该方法返回一个可以控制线程池内线程定时或周期性执行某任务的线程池。只不过和上面的区别是该线程池大小为1，而上面的可以指定线程池的大小。
         *
         * @return
         */
        public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
            return Executors.newSingleThreadScheduledExecutor(threadFactory);
        }
    }

    private static class ThreadPoolManagerClassHandler {
        private static final ThreadPoolManager THREAD_POOL_MANAGER = new ThreadPoolManager();
    }
}
